--- title: "日期问题" created: 2025-11-28 tags: - 算法 --- # 日期问题 ## 题目 [日期问题](https://www.acwing.com/problem/content/1231/) ![[image-84869fbe.png]] ## 思路分析 哈哈……一开始觉得没必要学 自己写 ![[image-44294a7f.png]] 一直打补丁 一下午被一道模拟题浪费了哈哈 看来确实需要学一些日期问题的小技巧 第一 用scanf读入 使用`scanf("%d/%d/%d", &a, &b, &c);` 可以在02/03/03这样的输入中提取到02 03 04这几个值 省去了很多麻烦的类型转换处理 用printf输出`printf("%d-%02d-%02d\n", year, month, day);` 可以将9月输出为09 又省去了一步处理 原理是输出占两位 不足的用0填补 第二 一个很常用的技巧 要什么日期 首先先把这段时间的合法的日期全都找出来 然后再对他们进行操作 类似于筛素数 先筛再操作 筛选也很简单 将日期用八位数表示 从起始到结束循环就行了 不用考虑多少进位的问题 多枚举那点不算什么 `for (int date = 19600101; date <= 20591231; date ++ ){` `int year = date / 10000, month = date % 10000 / 100, day = date % 100;` `if (check_valid(year, month, day))` `……` `}` `}` 如何判断是否是合法日期呢 首先年份没什么可看的 基本没什么限制 月份要是0~12 天数就比较复杂 用一个数组记录每个月应该有的天数 `int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};` 然后首先就是要在0~31的范围内 其次就是与某月应该有的天数进行比较 这里二月比较特殊 还要另外判断一个闰年 `bool check_valid(int year, int month, int day){` `if (month == 0 || month > 12)` `return false;` `if (day == 0 || day > 31)` `return false;` `int curdays=days[month];` `if(month==2)` `if(cur_year % 100 && cur_year % 4 == 0 || cur_year % 400 == 0)` `curdays+=1;` `if(day>curdays)` `return false;` `return true;` `}` 这种方式 泛用性也更强了 不像自己磨了一下午的代码 只适用于本题 换个题又得重写一堆逻辑 ## 代码实现 初版 ```cpp #include using namespace std; string date; int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int main() { cin>>date; int one=stoi(date.substr(0,2)); int two=stoi(date.substr(3,2)); int three=stoi(date.substr(6,2)); int date1=0,date2=0,date3=0; string ans1; if(two>0 && two<=12 && three>0 && three<=31){// yy/mm/dd int cur_year=one; if(cur_year>=60){ ans1=to_string(cur_year+1900); } else{ ans1=to_string(cur_year+2000); } int cur_month=two; // ans1+="-"; if(cur_month<10) ans1+="0"; ans1+=to_string(cur_month); int cur_day=three; // ans1+="-"; if(cur_day<10) ans1+="0"; ans1+=to_string(cur_day); int curdays=days[cur_month]; if(cur_month==2){ if(cur_year % 100 && cur_year % 4 == 0 || cur_year % 400 == 0){ curdays+=1; } } if(cur_day>curdays) ans1.clear(); if(!ans1.empty()) date1=stoi(ans1); } string ans2; if(one>0 && one<=31 && two>0 && two<=12){// dd/mm/yy int cur_year=three; if(cur_year>=60){ ans2=to_string(cur_year+1900); } else{ ans2=to_string(cur_year+2000); } int cur_month=two; // ans2+="-"; if(cur_month<10) ans2+="0"; ans2+=to_string(cur_month); int cur_day=one; // ans2+="-"; if(cur_day<10) ans2+="0"; ans2+=to_string(cur_day); int curdays=days[cur_month]; if(cur_month==2){ if(cur_year % 100 && cur_year % 4 == 0 || cur_year % 400 == 0){ curdays+=1; } } if(cur_day>curdays) ans2.clear(); if(!ans2.empty()) date2=stoi(ans2); } string ans3; if(one>0 && one<=12 && two>0 && two<=31){ //mm/dd/yy int cur_year=three; if(cur_year>=60){ ans3=to_string(cur_year+1900); } else{ ans3=to_string(cur_year+2000); } int cur_month=one; // ans3+="-"; if(cur_month<10) ans3+="0"; ans3+=to_string(cur_month); int cur_day=two; // ans3+="-"; if(cur_day<10) ans3+="0"; ans3+=to_string(cur_day); int curdays=days[cur_month]; if(cur_month==2){ if(cur_year % 100 && cur_year % 4 == 0 || cur_year % 400 == 0){ curdays+=1; } } if(cur_day>curdays) ans3.clear(); if(!ans3.empty()) date3=stoi(ans3); } // cout< heap; if(!ans1.empty()) heap.insert(date1); if(!ans2.empty()) heap.insert(date2); if(!ans3.empty()) heap.insert(date3); for(auto it=heap.begin();it!=heap.end();it++){ auto cur_date=*it; if(cur_date==date1){ ans1.insert(4,"-"); ans1.insert(7,"-"); cout<,greater> heap; // if(!ans1.empty()) // heap.push(date1); // if(!ans2.empty()) // heap.push(date2); // if(!ans3.empty()) // heap.push(date3); // while(!heap.empty()){ // auto cur_date=heap.top(); // heap.pop(); // if(cur_date==date1){ // ans1.insert(4,"-"); // ans1.insert(7,"-"); // cout< using namespace std; string date; int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; string processDate(int year, int month, int day) { string ans; if(year >= 60) ans = to_string(year + 1900); else ans = to_string(year + 2000); if(month < 10) ans += "0"; ans += to_string(month); if(day < 10) ans += "0"; ans += to_string(day); int curdays = days[month]; if(month == 2) { if(year % 100 && year % 4 == 0 || year % 400 == 0) { curdays += 1; } } if(day > curdays) ans.clear(); return ans; } int main() { cin >> date; int one = stoi(date.substr(0,2)); int two = stoi(date.substr(3,2)); int three = stoi(date.substr(6,2)); int date1 = 0, date2 = 0, date3 = 0; string ans1, ans2, ans3; if(two > 0 && two <= 12 && three > 0 && three <= 31) { // yy/mm/dd ans1 = processDate(one, two, three); } if(one > 0 && one <= 31 && two > 0 && two <= 12) { // dd/mm/yy ans2 = processDate(three, two, one); } if(one > 0 && one <= 12 && two > 0 && two <= 31) { // mm/dd/yy ans3 = processDate(three, one, two); } set heap; if(!ans1.empty()) heap.insert(stoi(ans1)); if(!ans2.empty()) heap.insert(stoi(ans2)); if(!ans3.empty()) heap.insert(stoi(ans3)); for(auto it = heap.begin(); it != heap.end(); it++) { string cur_date = to_string(*it); cur_date.insert(4, "-"); cur_date.insert(7, "-"); cout << cur_date << endl; } return 0; } ``` 267ms 虽然更慢 但是思路简单且移植性强 ```cpp #include using namespace std; int days[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; bool check_date(int year,int month,int day){ if(month==0 || month>12) return false; if(day==0 || day>31) return false; int curdays=days[month]; if(month==2) if(year%100 && year%4==0 || year%400==0) curdays++; if(day>curdays) return false; return true; } int main() { int one,two,three; scanf("%d/%d/%d",&one,&two,&three); for(int date=19600101;date<=20591231;date++){ int year=date/10000; //取前4位(砍掉后4位) / 4个0 int month=date%10000/100;//取后4位 %4个0 取后4位的前2位 再砍去2个0 int day=date%100; //取后2位 直接 %2个0 if(check_date(year,month,day)){ if(year%100==one && month==two && day==three || month==one && day==two && year%100==three || day==one && month==two && year%100==three) printf("%d-%02d-%02d\n",year,month,day); } } return 0; } ``` ## 同类题型 ## 视频讲解 --- ⬅️ [[日期计算|日期计算]] 🏠 [[00-刷题理模型]] ➡️ [[航班时间|航班时间]]